package org.csu.sei.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.csu.sei.common.BaseConstant;
import org.csu.sei.entity.Category;
import org.csu.sei.entity.DTO.CategoryDTO;
import org.csu.sei.entity.News;
import org.csu.sei.entity.Title;
import org.csu.sei.persistence.CategoryMapper;
import org.csu.sei.persistence.NewsMapper;
import org.csu.sei.persistence.TitleMapper;
import org.csu.sei.service.ICategoryService;
import org.csu.sei.service.ITitleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static org.csu.sei.common.BaseConstant.Status.INVISIBLE;
import static org.csu.sei.common.BaseConstant.Status.VISIBLE;

@Component(value = "categoryService")
public class CategoryServiceimpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    @Resource
    private CategoryMapper categoryMapper;

    @Resource
    private TitleMapper titleMapper;

    @Resource
    private NewsMapper newsMapper;

    @Resource
    private ITitleService titleService;

    private static final Logger logger = LoggerFactory.getLogger(CategoryServiceimpl.class);

    @Override
    public Category queryCategory(Long id) {
        return categoryMapper.selectById(id);
    }

    @Override
    public Category insertCategory(Category category) {
        Category parent = categoryMapper.selectById(category.getParentId());
        //父类型，父节点不存在
        if (parent==null && category.getParentId()!=0){
            category.setId(Long.parseLong("-1"));
            return category;
        }
        //如果该节点下有文章，则该节点时叶子节点，是不允许插入子节点的
        else if(
                newsMapper.selectCount(new QueryWrapper<News>().eq("cat_id",category.getParentId()))>0
               ){
            category.setId(Long.parseLong("-2"));
            return category;
        }
        //title在数据库不存在
        if(category.getTitleId()!=null){
            Title title=titleMapper.selectById(category.getTitleId());
            if(title==null){
                category.setId(Long.parseLong("-3"));
                return category;
            }
        }

        category.setCategoryStatus(VISIBLE.getCode());
        //默认为第一个
        int order = categoryMapper.selectMax();
        category.setSortOrder(order+1);
        category.setCreateTime(LocalDateTime.now());
        category.setUpdateTime(LocalDateTime.now());
        categoryMapper.insert(category);
        return category;
    }

    //删除父节点时，子节点的处理
    //删除父类型时，其子类型挂载到id为0的category下，文章设为不可见
    @Override
    public int deleteCategory(Long id) {
        List<Category> childrenCategoryList =categoryMapper.selectList(new QueryWrapper<Category>().eq("parent_id",id));
        for (Category category:childrenCategoryList) {
            //将子节点挂载到id为0的category下,并设置为不可见
            category.setParentId(Long.valueOf(0));
            category.setCategoryStatus(INVISIBLE.getCode());
            category.setSortOrder(0);
            categoryMapper.updateById(category);
            hideChildren(category.getId());
        }
        return categoryMapper.deleteById(id);
    }

    private void hideChildren(Long id){
        //子节点数量
        int childrenAmount = categoryMapper.selectCount(new QueryWrapper<Category>().eq("parent_id",id));
        //其下没有子节点，隐藏文章
        if(childrenAmount==0){
            newsMapper.changeStatusBySql(INVISIBLE.getCode(),id);
        }
        //基于有子节点就没有文章，有子节点，隐藏节点
        else{
            List<Category> childrenCategoryList =categoryMapper.selectList(new QueryWrapper<Category>().eq("parent_id",id));
            for (Category category:childrenCategoryList) {
                hideChildren(category.getId());
            }
        }
        categoryMapper.update(null,new UpdateWrapper<Category>().eq("id",id).set("category_status",INVISIBLE.getCode()));

    }

    @Override
    public int updateCategory(Category category) {
        Category primary=categoryMapper.selectById(category.getId());
        if(primary!=null){
            Category updateCategory = new Category();
            updateCategory.setId(category.getId());

            if( categoryMapper.selectById(category.getParentId())==null){
                return -2;
            }
            else if(
                    newsMapper.selectCount(new QueryWrapper<News>().eq("cat_id",category.getParentId()))>0
            ){
                return -5;
            }
            if( titleMapper.selectById(category.getTitleId())==null && category.getTitleId()!=null){
                return -3;
            }
            updateCategory.setParentId(category.getParentId());
            //需要判断title_id是否存在
            updateCategory.setTitleId(category.getTitleId());
            updateCategory.setName(category.getName());
            //原顺序
            updateCategory.setSortOrder(primary.getSortOrder());

            if(primary.getCategoryStatus()==INVISIBLE.getCode()){
                List<Category> categoryList = getTreeLeftCategoryList(primary.getId());
                for(Category cat:categoryList){
                    cat.setSortOrder(INVISIBLE.getCode());
                    newsMapper.changeStatusBySql(INVISIBLE.getCode(),cat.getId());
                    categoryMapper.updateById(cat);
                }
            }
            updateCategory.setCategoryStatus(category.getCategoryStatus());
            updateCategory.setCreateTime(primary.getCreateTime());
            updateCategory.setUpdateTime(LocalDateTime.now());

            Category checkCate;
            checkCate = categoryMapper.selectById(updateCategory.getParentId());
            while(checkCate.getId()!=0){
                if (checkCate.getParentId() == updateCategory.getId()){
                    return -4;
                }
                checkCate = categoryMapper.selectById(checkCate.getParentId());
            }
            System.out.println(updateCategory.toString());
            categoryMapper.updateById(updateCategory);

            if(categoryMapper.selectById(category.getId()).getTitleId()!=null)
            {
                titleService.checkName(categoryMapper.selectById(category.getId()).getTitleId());
            }
            return 0;

        }
        else{
            return -1;
        }
    }

    //获取一级子节点
    @Override
    public List<Category> queryChildren(Long id, boolean selectInviable) {
        QueryWrapper<Category> queryWrapper = new QueryWrapper();

        if(selectInviable){
            queryWrapper.eq("parent_id",id).orderByAsc("sort_order");
        }
        else{
            queryWrapper.eq("parent_id",id).eq("category_status",1).orderByAsc("sort_order");
        }
        List<Category> list= categoryMapper.selectList(queryWrapper);
        return list;
    }

    //查询所有的类别
    @Override
    public List<Category> queryAllCategory( boolean selectInviable){
        if(selectInviable){
            return categoryMapper.selectList(new QueryWrapper<Category>().orderByAsc("sort_order"));
        }
        else{
            QueryWrapper<Category> queryWrapper=new QueryWrapper<>();
            queryWrapper.eq("category_status",1).orderByAsc("sort_order");
            return categoryMapper.selectList(queryWrapper);
        }
    }


    //更改顺序、优先级
    @Override
    public int changeOrder(Long id,Long pid,List<Long> childrenOrder){
        logger.info("id"+id+" pid:"+pid);
        if(categoryMapper.selectById(id)==null){
            return -1;
        }
        else if(categoryMapper.selectById(pid)==null){
            return -2;
        }
        //父类型是一个存在文章的叶子节点，不允许成为父节点
        else if(
                newsMapper.selectCount(new QueryWrapper<News>().eq("cat_id",pid))>0
        ) {
            return -3;
        }
        Category category = categoryMapper.selectById(id);
        System.out.println("id"+id+" pid:"+pid);
        if(pid!=Integer.parseInt("0"))
        {
            UpdateWrapper<Category> updateWrapper = new UpdateWrapper<>();
            updateWrapper.set("title_id",null).lambda().eq(Category::getId,id);
            category.setTitleId(null);
            categoryMapper.update(null,updateWrapper);
        }
        category.setParentId(pid);
        category.setUpdateTime(LocalDateTime.now());
        categoryMapper.updateById(category);
        for (int i = 0; i < childrenOrder.size(); i++) {
            Category cat=categoryMapper.selectById(childrenOrder.get(i));
            if(cat==null){
                return -1;
            }
            cat.setSortOrder(i+1);
            cat.setUpdateTime(LocalDateTime.now());
            categoryMapper.updateById(cat);
        }
        return 0;
    }

    //更改可见不可见的状态
    @Override
    public int changeStatus(Long id){
        //想要改变状态的节点
        Category primary=categoryMapper.selectById(id);
        if(primary==null){
            return -1;
        }
        //有可见状态改为不可见状态，则所有子节点都改为不可见状态
        if(primary.getCategoryStatus()==VISIBLE.getCode()){
            primary.setUpdateTime(LocalDateTime.now());
            primary.setCategoryStatus(INVISIBLE.getCode());
            //修改子节点
            List<Category> children=categoryMapper.selectList(new QueryWrapper<Category>().eq("parent_id",id));
            for (Category category:children) {
                category.setUpdateTime(LocalDateTime.now());
                category.setCategoryStatus(INVISIBLE.getCode());
                //修改子节点下的文章
                List<News> newsList= newsMapper.selectList(new QueryWrapper<News>().eq("cat_id",category.getId()));
                for (News news : newsList) {
                    news.setNewsStatus(INVISIBLE.getCode());
                    news.setUpdateTime(LocalDateTime.now());
                    newsMapper.updateById(news);
                }
                categoryMapper.updateById(category);
            }
            categoryMapper.updateById(primary);
        }
        else{
            primary.setUpdateTime(LocalDateTime.now());
            primary.setCategoryStatus(VISIBLE.getCode());
            categoryMapper.updateById(primary);
        }
        return 0;
    }

    //修改类型的名称
    @Override
    public int changeCategoryName(Long id,String name){
        logger.info(id+" : "+name);
        Category category=categoryMapper.selectById(id);
        if(category==null){
            return -1;
        }
        category.setName(name);
        category.setUpdateTime(LocalDateTime.now());
        return categoryMapper.updateById(category);
    }

    //获取某一节点下的所有子节点
    @Override
    public List<Category> queryALLChildrenCategory(Long id, boolean selectInviable){
        List<Category> categoryList = new ArrayList<>();
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        if(selectInviable){
            queryWrapper.eq("parent_id",id).orderByAsc("sort_order");
        }
        else{
            queryWrapper.eq("parent_id",id).eq("category_status",1).orderByAsc("sort_order");
        }
        List<Category> childrenList = categoryMapper.selectList(queryWrapper);
        return childrenList;
    }

    //根据title分类查询所有可见category，过滤掉所有不可见的category
    @Override
    public List<Category> queryCategoryByTitleId(Long titleId,  boolean selectInviable){
        QueryWrapper<Category> queryWrapper=new QueryWrapper<>();
        if(selectInviable){
            queryWrapper.eq("title_id",titleId).orderByAsc("sort_order");
        }
        else{
            queryWrapper.eq("title_id",titleId).eq("category_status",1).orderByAsc("sort_order");
        }
        return categoryMapper.selectList(queryWrapper);
    }

    //前端的路由表，过滤掉所有不可见的category
    @Override
    public JSONObject router( boolean selectInviable){
        JSONObject jsonObject = new JSONObject();
        QueryWrapper<Category> queryWrapper = new QueryWrapper();
        if(selectInviable){
            queryWrapper.orderByAsc("sort_order");
        }
        else{
            queryWrapper.eq("category_status",1).orderByAsc("sort_order");
        }
        List<Category> categoryList = categoryMapper.selectList(queryWrapper);

        for (Category category : categoryList) {
            JSONObject json = new JSONObject();
            json.put("name",category.getName());
            json.put("pid",category.getParentId());
            json.put("cidList",chdList(category,selectInviable));
            jsonObject.put(category.getId().toString(),json);
        }
        return jsonObject;
    }


    public List<Long> chdList(Category category, boolean selectInviable){
        List<Category> categoryList= this.queryChildren(category.getId(),selectInviable);
        List<Long> chdList = new ArrayList<>();
        for (Category cate : categoryList) {
            chdList.add(cate.getId());
        }
        return chdList;
    }

    @Override
    public JSONArray tree(boolean includeHomePage){
        if (includeHomePage){
            JSONArray array = getTreeLeft(new Long(0));
            for (Long homeId:BaseConstant.HomePage.getHomePageCategory()) {
                Category category = categoryMapper.selectById(homeId);
                JSONObject json = new JSONObject();
                json.put("id",category.getId());
                json.put("name",category.getName());
                json.put("status",category.getCategoryStatus());
                json.put("disabled",category.getCategoryStatus()==0?true:false);
                json.put("hasPost",
                        newsMapper.selectCount(new QueryWrapper<News>().eq("cat_id",category.getId()))>0?true:false
                );
                array.add(json);
            }
            return array;
        }
        else{
            //所有的一级子节点
            return getTreeLeft(new Long(0));
        }
    }

    private JSONArray getTreeLeft(Long id){
        List<Category> categoryList = categoryMapper.selectList(
                new QueryWrapper<Category>().eq("parent_id",id).orderByAsc("sort_order")
        );
        if(categoryList.size()==0){
            return null;
        }
        else{
            JSONArray jsonArray = new JSONArray();
            for (Category category : categoryList) {
                if(!BaseConstant.HomePage.getHomePageCategory().contains(category.getId()))
                {
                    JSONObject json = new JSONObject();
                    json.put("id",category.getId());
                    json.put("name",category.getName());
                    json.put("status",category.getCategoryStatus());
                    json.put("disabled",category.getCategoryStatus()==0?true:false);
                    if(getTreeLeft(category.getId())!=null){
                        json.put("children",getTreeLeft(category.getId()));
                    }
                    json.put("hasPost",
                            newsMapper.selectCount(new QueryWrapper<News>().eq("cat_id",category.getId()))>0?true:false
                    );
                    jsonArray.add(json);
                }

            }
            return jsonArray;
        }
    }

    @Override
    public int deleteSome(List<Long> idList) {
        int count = 0;
        for (Long id : idList){
            count = count + deleteCategory(id);
        }
        return count;
    }

    @Override
    public int setLook(List<Long> idList, int status){
        for(Long id : idList){
            Category category = categoryMapper.selectById(id);
            category.setCategoryStatus(status);
            categoryMapper.updateById(category);
            newsMapper.changeStatusBySql(status,id);
        }
        return 1;
    }

    public JSONArray queryBar() {
        JSONArray array = new JSONArray();
        List<Title> titleList = titleMapper.selectList(null);
        for (Title title : titleList) {
            JSONObject json=new JSONObject();
            //该title下的category列表
            JSONArray categoryArray=new JSONArray();
            //获取该title下所有可见的category
            List<Category> categoryList = categoryMapper.selectList(
                    new QueryWrapper<Category>()
                            .eq("title_id",title.getId())
                            .eq("category_status",1)
                            .orderByAsc("sort_order")
            );
            json.put("title_name",title.getTitleName());
            json.put("title_id",title.getId());
            for (Category category:categoryList) {
                JSONObject categoryJson = new JSONObject();
                //获取这些可见的category下可见的子category
                List<Category> children = categoryMapper.selectList(
                        new QueryWrapper<Category>()
                                .eq("parent_id",category.getId())
                                .eq("category_status",1)
                                .orderByAsc("sort_order")
                );
                categoryJson.put("categoryName",category.getName());
                JSONArray itemList=new JSONArray();
                for (Category c:children) {
                    JSONObject child=new JSONObject();
                    child.put("name",c.getName());
                    child.put("id",+c.getId());
                    itemList.add(child);
                }
                categoryJson.put("itemList",itemList);
                categoryArray.add(categoryJson);
            }
            json.put("categoryList",categoryArray);
            array.add(json);
        }
        return array;
    }

    @Override
    public LocalDateTime getLatestUpdateTime(Long id){
        if(categoryMapper.selectById(id)==null){
            return null;
        }
        List<Category> categoryList=new ArrayList<>();
        //加入子节点类型
        categoryList.addAll(categoryMapper.selectList(
                new QueryWrapper<Category>()
                        .eq("parent_id",id)
                        .eq("category_status",1)
                        .select("id","update_time")
                        .orderByAsc("sort_order")
                        .orderByDesc("update_time")
        ));
        //加入本节点类型
        categoryList.add(categoryMapper.selectOne(
                new QueryWrapper<Category>().eq("id",id).select("id","update_time").orderByAsc("sort_order")
        ));

        QueryWrapper<News> queryWrapper=new QueryWrapper<>();
        List<Long> idList = new ArrayList<>();
        for (Category c:categoryList) {
            idList.add(c.getId());
        }
        queryWrapper.eq("news_status",1)
                .in("id",idList)
                .orderByDesc("update_time")
                .orderByAsc("list_order");
        List<News> newsList= newsMapper.selectList(queryWrapper);
        return newsList.size()>0?newsList.get(0).getUpdateTime():categoryList.get(0).getUpdateTime();
    }

    @Override
    public int changeTitleCategory(Long id,Long tid){
        if(categoryMapper.selectById(id)==null){
            return -1;
        }
        else if(titleMapper.selectById(tid)==null){
            return -2;
        }
        Category category = categoryMapper.selectById(id);
        Long primaryTitleId = category.getTitleId();
        if(primaryTitleId!=tid){
            category.setTitleId(tid);
            categoryMapper.updateById(category);
        }
        if(categoryMapper.selectCount(new QueryWrapper<Category>().eq("title_id",primaryTitleId))==1)
        {
            Title title= titleMapper.selectById(primaryTitleId);
            String name = categoryMapper.selectList(new QueryWrapper<Category>().eq("title_id",primaryTitleId).orderByAsc("sort_order")).get(0).getName();
            title.setTitleName(name);
            titleMapper.updateById(title);
        }
        if(categoryMapper.selectCount(new QueryWrapper<Category>().eq("title_id",tid))==1)
        {
            Title title= titleMapper.selectById(tid);
            String name = categoryMapper.selectList(new QueryWrapper<Category>().eq("title_id",tid).orderByAsc("sort_order")).get(0).getName();
            title.setTitleName(name);
            titleMapper.updateById(title);
        }
        return  0;
    }

    @Override
    public JSONObject titleCategoryList()
    {
        JSONObject jsonObject = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        List<Title> titleList=titleMapper.selectList(null);
        for (Title t : titleList) {
            JSONObject json = new JSONObject();
            json.put("titleId",t.getId());
            json.put("titleName",t.getTitleName());
            List<Category> categoryList = categoryMapper.selectList(new QueryWrapper<Category>().select("id","name").eq("title_id",t.getId()).eq("parent_id",Long.parseLong("0")));
            List<CategoryDTO> categoryDTOS = new ArrayList<>();
            for(Category category : categoryList){
                if(!BaseConstant.HomePage.getHomePageCategory().contains(category.getId())){
                    CategoryDTO categoryDTO = CategoryDTO.returnCategory(category);
                    categoryDTOS.add(categoryDTO);
                }
            }
            json.put("categoryList",categoryDTOS);
            jsonArray.add(json);
        }
        jsonObject.put("titleList",jsonArray);
        List<CategoryDTO> categoryDTOS = new ArrayList<>();
        for(Category category:this.getUnusedCategory())
        {
            if(!BaseConstant.HomePage.getHomePageCategory().contains(category.getId()))
            {
                CategoryDTO categoryDTO = CategoryDTO.returnCategory(category);
                categoryDTOS.add(categoryDTO);
            }
        }
        jsonObject.put("unusedList",categoryDTOS);
        return jsonObject;
    }

    @Override
    public int changeUsedCategory(List<Long> used) {
        QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",Long.parseLong("0"));
        for(Long id:used){
            queryWrapper.ne("id",id);
        }
        List<Category> categoryList = categoryMapper.selectList(queryWrapper);
        for(Category category:categoryList){
            if(!BaseConstant.HomePage.getHomePageCategory().contains(category.getId()))
            {
                UpdateWrapper<Category> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("title_id",null).lambda().eq(Category::getId,category.getId());
                categoryMapper.update(null,updateWrapper);
            }
        }
        return 0;
    }

    public List<Category> getTreeLeftCategoryList(Long id){
        List<Category> children = categoryMapper.selectList(new QueryWrapper<Category>().eq("parent_id",id));
        //是一个叶子节点
        List<Category> allChildren = new ArrayList<>();
        allChildren.addAll(children);
        for(Category child:children)
        {
            List<Category> childChildren = getTreeLeftCategoryList(child.getId());
            allChildren.addAll(childChildren);
        }
        return allChildren;
    }


    @Override
    public int changeOrder(Long id,int order)
    {
        Category category = categoryMapper.selectById(id);
        category.setSortOrder(order);
        return categoryMapper.updateById(category);
    }

    @Override
    public List<Category> getUnusedCategory(){
        List<Category> categoryList=categoryMapper.getTitleNullFirstCategory();
        for (int i=categoryList.size()-1 ; i>=0; --i) {
            Category category = categoryList.get(i);
            if (BaseConstant.HomePage.getHomePageCategory().contains(category.getId()) || category.getCategoryStatus()==INVISIBLE.getCode())
            {
                categoryList.remove(category);
            }
        }
        return  categoryList;
    }

    @Override
    public  int changeUnusedCategoryOrder(int startOrder)
    {
        List<Category> categoryList = this.getUnusedCategory();
        int index = startOrder;
        for (Category category : categoryList) {
            category.setSortOrder(index);
            index+=1;
            categoryMapper.updateById(category);
        }
        return 0;
    }
    @Override
    public int getCount(){
        return categoryMapper.selectCount(null);
    }
}
